﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Cesave.Domain.Core;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Domain.PermisosModule.Resources;

namespace Cesave.Domain.PermisosModule.Contracts.Municipios
{
	/// <summary>
	/// 
	/// </summary>
	public class MunicipioService
		: IMunicipioService
	{
		#region Private properties

		/// <summary>
		/// 
		/// </summary>
		private readonly IMunicipioRepository _municipioRepository;

		#endregion

		#region Constructor

		/// <summary>
		/// 
		/// </summary>
		/// <param name="municipioRepository"></param>
		public MunicipioService(IMunicipioRepository municipioRepository)
		{
			if (municipioRepository == null)
				throw new ArgumentNullException("municipioRepository", Messages.exception_DependenciesAreNotInitialized);
			_municipioRepository = municipioRepository;
		}

		#endregion

		#region IMunicipioService Members

		/// <summary>
		/// 
		/// </summary>
		/// <param name="estadoGuid"></param>
		/// <returns></returns>
		public List<Municipio> FindMunicipiosByEstado(Guid estadoGuid)
		{
			if (estadoGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			MunicipiosByEstadoSpecification municipiosByEstadoSpecification = new MunicipiosByEstadoSpecification(estadoGuid);
			return _municipioRepository.FindMunicipiosByEstadoSpecification(municipiosByEstadoSpecification).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="estadoGuid"></param>
		/// <param name="status"></param>
		/// <returns></returns>
		public List<Municipio> FindMunicipiosByEstadoAndStatus(Guid estadoGuid, bool status = true)
		{
			if (estadoGuid == Guid.Empty)
				throw new InvalidOperationException("estadoGuid");
			MunicipiosByEstadoSpecification municipiosByEstadoSpecification = new MunicipiosByEstadoSpecification(estadoGuid);
			return _municipioRepository.FindMunicipiosByEstadoSpecificationAndStatus(municipiosByEstadoSpecification, status).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distritoGuid"></param>
		/// <returns></returns>
		public List<Municipio> FindMunicipiosByDistrito(Guid distritoGuid)
		{
			if (distritoGuid == Guid.Empty)
				throw new InvalidOperationException("distritoGuid");
			MunicipiosByDistritoSpecification municipiosByDistritoSpecification = new MunicipiosByDistritoSpecification(distritoGuid);
			return _municipioRepository.FindMunicipiosByDistritoSpecification(municipiosByDistritoSpecification).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distritoGuid"></param>
		/// <param name="status"></param>
		/// <returns></returns>
		public List<Municipio> FindMunicipiosByDistritoAndStatus(Guid distritoGuid, bool status = true)
		{
			if (distritoGuid == Guid.Empty)
				throw new InvalidOperationException(Messages.exception_InvalidArgument);
			MunicipiosByDistritoSpecification municipiosByDistritoSpecification = new MunicipiosByDistritoSpecification(distritoGuid);
			return _municipioRepository.FindMunicipiosByDistritoSpecificationAndStatus(municipiosByDistritoSpecification, status).ToList();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="municipioGuid"></param>
		/// <returns></returns>
		public Municipio FindMunicipioByGuid(Guid municipioGuid)
		{
			if (municipioGuid == Guid.Empty)
				throw new InvalidCastException(Messages.exception_InvalidArgument);
			MunicipioByGuidSpecification municipioByGuidSpecification = new MunicipioByGuidSpecification(municipioGuid);
			return _municipioRepository.FindMunicipioByGuidSpecification(municipioByGuidSpecification);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="municipio"></param>
		public void AddMunicipio(Municipio municipio)
		{
			if (municipio == null)
				throw new ArgumentNullException("municipio", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _municipioRepository.StoreContext;
			_municipioRepository.Add(municipio);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="municipio"></param>
		public void ChangeMunicipio(Municipio municipio)
		{
			if (municipio == null)
				throw new ArgumentNullException("municipio", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _municipioRepository.StoreContext;
			_municipioRepository.Modify(municipio);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="municipio"></param>
		public void DeleteMunicipio(Municipio municipio)
		{
			if (municipio == null)
				throw new ArgumentNullException("municipio", Messages.exception_InvalidArgument);
			IUnitOfWork unitOfWork = _municipioRepository.StoreContext;
			_municipioRepository.Remove(municipio);
			try
			{
				unitOfWork.Commit();
			}
			catch (OptimisticConcurrencyException)
			{
				unitOfWork.RollbackChanges();
				unitOfWork.CommitAndRefreshChanges();
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			if (_municipioRepository != null &&
				_municipioRepository.StoreContext != null)
				_municipioRepository.StoreContext.Dispose();
		}

		#endregion
	}
}
